<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>xeokit Example</title>
    <link href="../css/pageStyle.css" rel="stylesheet"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js"></script>
    <script src="../libs/dat.gui.min.js" type="text/javascript"></script>
    <link href="../css/dat-gui-light-style.css" rel="stylesheet"/>
    <style>
        #warningMessage {
            position: absolute;
            font-size: 18px;
            left: 75px;
            top: 70px;
            pointer-events: all;
            color: red;
            width: 250px;
        }
    </style>
</head>
<body>
<input type="checkbox" id="info-button"/>
<label for="info-button" class="info-button"><i class="far fa-3x fa-question-circle"></i></label>
<canvas id="myCanvas"></canvas>
<div id="warningMessage"></div>
<canvas id="myNavCubeCanvas"></canvas>
<div class="slideout-sidebar">
    <h1>SAO</h1>
    <h2>Scalable Ambient Obscurance</h2>
    <p>SAO is a visual effect that darkens the crevices in models, to emphasis geometric details.</p>
    <h3>Stats</h3>
    <ul>
        <li>
            <div id="time">Loading JavaScript modules...</div>
        </li>
    </ul>
    <h3>Customize SAO</h3>
    <div id="myDatGuiContainer"></div>
    <h3>Components Used</h3>
    <ul>
        <li>
            <a href="../../docs/class/src/viewer/Viewer.js~Viewer.html"
               target="_other">Viewer</a>
        </li>
        <li>
            <a href="../../docs/class/src/plugins/XKTLoaderPlugin/XKTLoaderPlugin.js~XKTLoaderPlugin.html"
               target="_other">XKTLoaderPlugin</a>
        </li>
        <li>
            <a href="../../docs/class/src/viewer/scene/postfx/SAO.js~SAO.html"
               target="_other">SAO</a>
        </li>
    </ul>
    <h3>Resources</h3>
    <ul>
        <li>
            <a href="http://openifcmodel.cs.auckland.ac.nz/Model/Details/301"
               target="_other">Model source</a>
        </li>
    </ul>
</div>
</body>

<script type="module">

    //------------------------------------------------------------------------------------------------------------------
    // Import the modules we need for this example
    //------------------------------------------------------------------------------------------------------------------

    import {Viewer, XKTLoaderPlugin} from "../../dist/xeokit-sdk.min.es.js";

    //------------------------------------------------------------------------------------------------------------------
    // Create a Viewer, arrange the camera, tweak xraying and highlight materials
    //------------------------------------------------------------------------------------------------------------------

    const viewer = new Viewer({
        canvasId: "myCanvas",
        transparent: true,
        saoEnabled: true // <<------------------- Enable SAO
    });

    if (!viewer.scene.sao.supported) {
        document.getElementById("warningMessage").innerText = "SAO is not currently supported in this browser";
    }

    const cameraControl = viewer.cameraControl;
    const scene = viewer.scene;
    const cameraFlight = viewer.cameraFlight;
    const sao = scene.sao;
    const camera = scene.camera;

    sao.enabled = true; // Only works if supported (see above)

    cameraControl.followPointer = true;
    cameraControl.dollyInertia = 0;
    cameraControl.mouseWheelDollyRate = 40;

    camera.eye = [10.45, 17.38, -98.31];
    camera.look = [43.09, 0.5, -26.76];
    camera.up = [0.06, 0.96, 0.16];

    camera.perspective.near = 0.1;
    camera.perspective.far = 5000.0;

    camera.ortho.near = 0.1;
    camera.ortho.far = 5000.0;

    camera.projection = "perspective";

    scene.highlightMaterial.fill = true;
    scene.highlightMaterial.fillAlpha = 0.3;
    scene.highlightMaterial.edgeColor = [1, 1, 0];

    //----------------------------------------------------------------------------------------------------------------------
    // Load a model and fit it to view
    //----------------------------------------------------------------------------------------------------------------------

    const xktLoader = new XKTLoaderPlugin(viewer);

    const sceneModel = xktLoader.load({
        id: "myModel",
        src: "../../assets/models/xkt/v8/ifc/OTCConferenceCenter.ifc.xkt",
        edges: true,
        saoEnabled: true, // Allows SAO to be applied to the model (default is true)
        objectDefaults: { // This model has opaque windows / spaces; make them transparent
            "IfcPlate": {
                opacity: 0.3 // These are used as windows in this model - make transparent
            },
            "IfcWindow": {
                opacity: 0.4
            }
        },
        excludeTypes: ["IfcSpace"]
    });


    const t0 = performance.now();
    document.getElementById("time").innerHTML = "Loading model...";
    sceneModel.on("loaded", function () {
        const t1 = performance.now();
        document.getElementById("time").innerHTML = "Model loaded in " + Math.floor(t1 - t0) / 1000.0 + " seconds<br>Objects: " + sceneModel.numEntities;

        cameraFlight.jumpTo({
            eye: [3.6930694580078125, 5.834853649139404, -23.98213005065918],
            look: [84.31920623779297, -29.88751792907715, -116.21513366699219],
            up: [0.18424127995967865, 0.9600174427032471, -0.21076446771621704]
        });
    });

    //------------------------------------------------------------------------------------------------------------------
    // GUI to play with SAO parameters
    //------------------------------------------------------------------------------------------------------------------

    const saoParams = new function () {
        this.enabled = sao.enabled;
        this.kernelRadius = sao.kernelRadius;
        this.intensity = sao.intensity;
        this.bias = sao.bias;
        this.scale = sao.scale;
        this.minResolution = sao.minResolution;
        this.numSamples = sao.numSamples;
        this.blendFactor = sao.blendFactor;
        this.blendCutoff = sao.blendCutoff;
        this.blur = sao.blur;
        this.perspective = (camera.projection === "perspective");
        this.far = camera.perspective.far;
        this.fov = camera.perspective.fov;
    }();

    const update = function () {
        sao.enabled = saoParams.enabled;
        sao.kernelRadius = saoParams.kernelRadius;
        sao.intensity = saoParams.intensity;
        sao.bias = saoParams.bias;
        sao.scale = saoParams.scale;
        sao.minResolution = saoParams.minResolution;
        sao.numSamples = saoParams.numSamples;
        sao.blendFactor = saoParams.blendFactor;
        sao.blendCutoff = saoParams.blendCutoff;
        sao.blur = saoParams.blur;
        camera.projection = saoParams.perspective ? "perspective" : "ortho";
        camera.perspective.far = saoParams.far;
        camera.ortho.far = saoParams.far;
        camera.perspective.fov = saoParams.fov;
        requestAnimationFrame(update);
    };

    update();

    const gui = new dat.GUI({autoPlace: false, width: "100%"});

    const saoFolder = gui.addFolder('SAO');
    saoFolder.add(saoParams, 'enabled');
    saoFolder.add(saoParams, 'bias', -2, 2);
    saoFolder.add(saoParams, 'intensity', 0, 1.0);
    saoFolder.add(saoParams, 'scale', .05, 5);
    saoFolder.add(saoParams, 'kernelRadius', 1, 200);
    saoFolder.add(saoParams, 'minResolution', 0, 0.001);
    saoFolder.add(saoParams, 'numSamples', 4, 100);
    saoFolder.add(saoParams, 'blendFactor', 0, 2);
    saoFolder.add(saoParams, 'blendCutoff', 0, 2);
    saoFolder.add(saoParams, 'blur');
    saoFolder.open();

    const cameraFolder = gui.addFolder('Camera');
    cameraFolder.add(saoParams, 'perspective');
    cameraFolder.add(saoParams, 'far', 100, 20000);
    cameraFolder.add(saoParams, 'fov', 10, 120);
    cameraFolder.open();

    const customContainer = document.getElementById('myDatGuiContainer');
    customContainer.appendChild(gui.domElement);

</script>
</html>
